package cn.sylinx.hbatis.db.common;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

import cn.sylinx.hbatis.db.cache.CacheQuery;
import cn.sylinx.hbatis.db.dialect.Dialect;
import cn.sylinx.hbatis.db.mapper.QueryMapper;
import cn.sylinx.hbatis.kit.Ret;
import cn.sylinx.hbatis.plugin.datasource.JdbcResourcePlugin;

/**
 * 默认HbatisService实现
 * 
 * @author han
 *
 */
public class DefaultHbatisService implements HbatisService, BaseDbOper {

	/**
	 * DbPro对象
	 */
	private final DbPro dbPro;

	/**
	 * 缓存查询对象
	 */
	private final CacheQuery cacheQuery;

	/**
	 * 缓存HbatisService对象
	 */
	private final Map<String, HbatisService> map = new WeakHashMap<String, HbatisService>();

	/**
	 * 构造器
	 */
	public DefaultHbatisService() {
		this(JdbcResourcePlugin.DEFAULT_JDBC_RESOURCE_NAME);
	}

	public DefaultHbatisService(String datasourceName) {
		this(DbPro.use(datasourceName));
	}

	/**
	 * 构造器
	 * 
	 * @param dbPro
	 *            DbPro对象
	 */
	private DefaultHbatisService(DbPro dbPro) {
		this.dbPro = dbPro;
		cacheQuery = createCacheQuery();
		map.put(dbPro.getDataSourceName(), this);
	}

	@Override
	public String getDatasourceName() {
		return dbPro.getDataSourceName();
	}

	@Override
	public Dialect getDialect() {
		return dbPro.getDialect();
	}

	@Override
	public <T> T call(Callable<T> callable) {
		return dbPro.call(callable);
	}

	/**
	 * 创建缓存查询对象
	 * 
	 * @param params
	 * @return
	 */
	private CacheQuery createCacheQuery(Object... params) {
		return new DefaultCacheQuery(this.dbPro);
	}

	public HbatisService use(String jdbcResourceName) {

		HbatisService dbService = map.get(jdbcResourceName);
		if (dbService == null) {

			synchronized (jdbcResourceName.intern()) {
				createInstanceInner(jdbcResourceName);
			}

			dbService = map.get(jdbcResourceName);
		}

		return dbService;
	}

	private void createInstanceInner(String jdbcResourceName) {

		HbatisService dbService = map.get(jdbcResourceName);
		if (dbService == null) {
			dbService = new DefaultHbatisService(DbPro.use(jdbcResourceName));
			map.put(jdbcResourceName, dbService);
		}
	}

	@Override
	public CacheQuery withCache() {
		if (cacheQuery == null) {
			throw new UnsupportedOperationException("不支持缓存查询");
		}

		return cacheQuery;
	}

	protected CacheQuery getCacheQuery() {
		return cacheQuery;
	}

	public boolean transaction(ITransaction transaction) {
		return dbPro.transaction(transaction);
	}

	@Override
	public Ret transactionWithReturn(ITransaction transaction) {
		return dbPro.transactionWithReturn(transaction);
	}

	public <T> List<T> query(final String sql, final QueryMapper<T> mapper, final Object... params) {
		return dbPro.query(sql, mapper, params);
	}

	public <T> T queryFirst(final String sql, final QueryMapper<T> mapper, final Object... params) {
		return dbPro.queryFirst(sql, mapper, params);
	}

	public List<Object[]> query(final String sql, final Object... params) {
		return dbPro.query(sql, params);
	}

	public List<Map<String, Object>> queryMap(final String sql, final Object... params) {
		return dbPro.queryMap(sql, params);
	}

	public Object[] queryFirst(String sql, Object... params) {
		return dbPro.queryFirst(sql, params);
	}

	public Map<String, Object> queryFirstMap(String sql, Object... params) {
		return dbPro.queryFirstMap(sql, params);
	}

	public Serializable save(String insertSql, Object... params) {
		return dbPro.save(insertSql, params);
	}

	public int update(String updateSql, Object... params) {
		return dbPro.update(updateSql, params);
	}

	public Serializable updateWithReturnPk(String updateSql, Object... params) {
		return dbPro.updateWithReturnPk(updateSql, params);
	}

	public int[] batch(List<String> sql) {
		return dbPro.batch(sql);
	}

	public int[] batch(String sql, Object[][] params) {
		return dbPro.batch(sql, params);
	}

	public int[] batch(String sql, Object[][] params, final int batchSize) {
		return dbPro.batch(sql, params, batchSize);
	}

	public int[] batch(List<String> sqlList, int batchSize) {
		return dbPro.batch(sqlList, batchSize);
	}

	public <T> int update(T t) {
		return dbPro.update(t);
	}

	public <T> Serializable save(T t) {
		return dbPro.save(t);
	}

	public <T> int delete(T t) {
		return dbPro.delete(t);
	}

	@Override
	public Record queryFirstRecord(String sql, Object... params) {
		return dbPro.queryFirstRecord(sql, params);
	}

	@Override
	public List<Record> queryRecords(String sql, Object... params) {
		return dbPro.queryRecords(sql, params);
	}

	@Override
	public boolean execute(String exeSql, Object... params) {
		return dbPro.execute(exeSql, params);
	}

	@Override
	public boolean executeLargeUpdate(final List<String> exeSqlList) {
		return dbPro.executeLargeUpdate(exeSqlList);
	}

	@Override
	public DbOper getDbOper() {
		return this;
	}

	@Override
	public boolean existTable(String schema, String table) {
		return dbPro.existTable(schema, table);
	}

	@Override
	public boolean existTableColumn(String schema, String table, String column) {
		return dbPro.existTableColumn(schema, table, column);
	}

	@Override
	public <T> List<T> queryObject(String sql, Class<T> clazz, Object... params) {
		return dbPro.queryObject(sql, clazz, params);
	}

	@Override
	public <T> T queryFirstObject(String sql, Class<T> clazz, Object... params) {
		return dbPro.queryFirstObject(sql, clazz, params);
	}

}
